package com.budwk.app.uc.services.impl;

import cn.hutool.core.util.ObjUtil;
import com.budwk.app.base.gmpass.SM4Util;
import com.budwk.app.common.config.AppException;
import com.budwk.app.exception.ServiceException;
import com.budwk.app.exception.SqfwExceptionCodeEnum;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.models.Sys_user_security;
import com.budwk.app.sys.services.SysRoleUserService;
import com.budwk.app.sys.services.SysUnitService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.uc.services.AuthService;
import com.budwk.app.uc.services.ValidateService;
import com.budwk.starter.common.constant.RedisConstant;
import com.budwk.starter.common.exception.BaseException;
import jodd.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.random.R;

/**
 * 认证服务
 *
 * @author wizzer@qq.com
 */
@IocBean
public class AuthServiceImpl implements AuthService {

    @Inject
    private ValidateService validateService;

    @Inject
    private SysUserService sysUserService;

    @Inject
    private RedisService redisService;

    @Inject
    private SysUnitService sysUnitService;
    @Inject
    private SysRoleUserService sysRoleUserService;


    // 等待时间(s)
    private final static int CHECK_WAIT_TIME = 20 * 60;
    // 用户名次数
    private final static int CHECK_COUNT = 3;

    public Sys_user loginByPassword(String loginname, String password,
                                    String key, String code) throws BaseException {
        Sys_user_security security = sysUserService.getUserSecurity();
        if (security != null && security.getCaptchaHasEnabled() != null && security.getCaptchaHasEnabled()) {
            validateService.checkCode(key, code);
        }
        return sysUserService.loginByPassword(loginname, password);
    }


    public Sys_user loginByPasswordNew(String loginname, String password,
                                       String key, String code, String rsaDeviceId) throws BaseException {
        Sys_user_security security = sysUserService.getUserSecurity();
        if (security != null && security.getCaptchaHasEnabled() != null && security.getCaptchaHasEnabled()) {
            validateService.checkCode(key, code);
        }
        return sysUserService.loginByPasswordNew(loginname, password, rsaDeviceId);
    }

    public Sys_user loginByMobile(String mobile, String code) throws BaseException {
        validateService.checkSMSCode(mobile, code);
        return sysUserService.loginByMobile(mobile);
    }

    public void checkLoginName(String loginName, String ip, boolean nameRetryLock, int nameRetryNum, int nameTimeout) throws BaseException {
        if (nameRetryLock) {
            int count = Integer.parseInt(Strings.sNull(redisService.get(RedisConstant.PRE + "checkLoginname:" + ip), "0"));
            if (count > nameRetryNum - 1) {
                long ttl = redisService.ttl(RedisConstant.PRE + "checkLoginname:" + ip);
                long m = ttl / 60;
                long s = ttl % 60;
                throw new ServiceException(String.format("您的IP已被锁定，请%s分钟%s秒后重试", m, s));
            }
            try {
                sysUserService.checkLoginName(loginName);
            } catch (ServiceException exception) {
                if (exception.getCode().equals(SqfwExceptionCodeEnum.USER_NOT_EXIST.getCode())) {
                    redisService.setex(RedisConstant.PRE + "checkLoginname:" + ip, nameTimeout, String.valueOf(++count));
                }
                throw new BaseException("账号尚未获得授权,请联系街道管理员获得授权");
            }
        } else {
            sysUserService.checkLoginName(loginName);
        }
    }

    public void checkMobile(String mobile, String ip, boolean nameRetryLock, int nameRetryNum, int nameTimeout) throws BaseException {
        if (nameRetryLock) {
            int count = Integer.parseInt(Strings.sNull(redisService.get(RedisConstant.PRE + "checkMobile:" + ip), "0"));
            if (count > nameRetryNum - 1) {
                long ttl = redisService.ttl(RedisConstant.PRE + "checkMobile:" + ip);
                long m = ttl / 60;
                long s = ttl % 60;
                throw new BaseException(String.format("您的IP已被锁定，请%s分钟%s秒后重试", m, s));
            }
            try {
                sysUserService.checkMobile(mobile);
            } catch (ServiceException exception) {
                if (exception.getCode().equals(SqfwExceptionCodeEnum.USER_PHONE_NOT_EXIST.getCode())) {
                    redisService.setex(RedisConstant.PRE + "checkMobile:" + ip, nameTimeout, String.valueOf(++count));
                }
                throw new ServiceException("账号尚未获得授权,请联系街道管理员获得授权");
            }
        } else {
            sysUserService.checkMobile(mobile);
        }
    }


    public Sys_user getUserByLoginname(String loginname, String ip, boolean nameRetryLock, int nameRetryNum, int nameTimeout) throws BaseException {
        if (nameRetryLock) {
            int count = Integer.parseInt(Strings.sNull(redisService.get(RedisConstant.PRE + "getUserByLoginname:" + ip), "0"));
            if (count > nameRetryNum - 1) {
                long ttl = redisService.ttl(RedisConstant.PRE + "getUserByLoginname:" + ip);
                long m = ttl / 60;
                long s = ttl % 60;
                throw new BaseException(String.format("您的IP已被锁定，请%s分钟%s秒后重试", m, s));
            }
            try {
                return sysUserService.getUserByLoginname(loginname);
            } catch (BaseException baseException) {
                if (baseException.getMessage().equals("用户不存在")) {
                    redisService.setex(RedisConstant.PRE + "getUserByLoginname:" + ip, nameTimeout, String.valueOf(++count));
                }
                throw baseException;
            }
        } else {
            return sysUserService.getUserByLoginname(loginname);
        }
    }

    public Sys_user getUserById(String id) throws BaseException {
        return sysUserService.getUserById(id);
    }

    public void setPwdByLoginname(String loginname, String password) throws BaseException {
        sysUserService.setPwdByLoginname(loginname, password);
    }

    public void setPwdById(String id, String password) throws BaseException {
        sysUserService.setPwdById(id, password);
    }

    @Override
    public Sys_user registerUser(Sys_user user) throws Exception {
        Sys_user showUser = sysUserService.fetch(Cnd.where(Sys_user::getLoginname, "=", user.getLoginname()));
        if (ObjUtil.isNotEmpty(showUser)) {
            throw new RuntimeException("用户已经注册");
        }
        sysUserService.checkPassword(user, user.getPassword());
        Sys_unit sys_unit = sysUnitService.fetch("47a2303ef34e49a2882dc62ec2896381");

        String key = SM4Util.generateKey();
        ;
        //序号查询
        Sql sql = Sqls.create("select max(CAST(serialNo as int)) from shequ.sys_user");
        sql.setCallback(Sqls.callback.integer());
        sysUserService.dao().execute(sql);

        //设置用户信息
        String cipher = SM4Util.encryptEcb(key, user.getPassword());
        user.setPassword(cipher);
        user.setSm4PassKey(key);
        user.setPassword(cipher);
        user.setSex(user.getSex() == null ? 0 : user.getSex());
        user.setLoginCount(0);
        user.setNeedChangePwd(false);
        user.setUnitId(sys_unit.getId());
        user.setUnit(sys_unit);
        user.setUnitName(sys_unit.getName());
        user.setUnitPath(sys_unit.getPath());
        user.setSerialNo(String.valueOf(sql.getInt() + 1));

        user.setPwdResetAt(System.currentTimeMillis());
        sysUserService.insert(user);

        //插入用户角色表
        sysRoleUserService.insert("shequ.sys_role_user", Chain.make("id", R.UU32()).add("userId", user.getId()).add("roleId", "a04c91721a9841bb9538f1ae1f085043"));
        return user;
    }

    @Override
    public Sys_user loginByPasswordForThird(String loginname, String password) throws BaseException {
        return sysUserService.loginByPassword(loginname, password);
    }

    @Override
    public Sys_user loginByPasswordAndSmsCode(String loginname, String password, String code) {
        if (StringUtils.isEmpty(loginname) || StringUtils.isEmpty(password)) {
            throw new AppException("用户或密码不能为空！");
        }
        Sys_user sysUser = sysUserService.loginByPassword(loginname, password);
        if (null == sysUser) {
            throw new AppException("用户名或密码错误！");
        }
        if (StringUtils.isEmpty(code)) {
            throw new AppException("短信验证码不能为空！");
        }
        sysUser = loginByMobile(loginname, code);
        if (null == sysUser) {
            throw new AppException("短信验证码不正确！");
        }
        return sysUser;
    }
}
